
package peertopeerserver;

import java.net.*;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class PeerToPeerServer extends Thread{
    
    private Socket serverConnection;
    private String serverTimeStamp;
    private int ID;
    private static List<MyFile> fileList = null;
    private MyFile file;
    private FileManipulation fileManipulation;
    private String[] fileListReceived;
    private Object clientSocket;
    
    public PeerToPeerServer(Socket serverSocket, int ID){
        this.serverConnection = serverSocket;
        this.ID = ID;
    }
       
    public void receiveFile(String fileName){
        BufferedInputStream bufferedInputStream = null;
        try {
            /* Receive File. */
            File newVersion = new File(fileName);
            FileOutputStream fileOutputStream = new FileOutputStream(newVersion);
            bufferedInputStream = new BufferedInputStream(serverConnection.getInputStream());
            InputStreamReader inputStreamReader = new InputStreamReader(bufferedInputStream);
            int readChareactere;
            while((readChareactere = inputStreamReader.read()) != -1){
                fileOutputStream.write(readChareactere);
            }
            
            /* Send Confirmation. */
            String sentMessage = "ACK" + (char)13;
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(serverConnection.getOutputStream());
            OutputStreamWriter outputStreamWritter = new OutputStreamWriter(bufferedOutputStream);
            outputStreamWritter.write(sentMessage);
            outputStreamWritter.flush();
            
        } catch (IOException ex) {
            Logger.getLogger(PeerToPeerServer.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                bufferedInputStream.close();
            } catch (IOException ex) {
                Logger.getLogger(PeerToPeerServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    public void SendFile(String fileName){
        FileInputStream fileInputStream = null;
        StringBuffer receivedMessageBuffer = null;
        String receivedMessage;
        try {
            /* Send File. */
            File sentFile = new File(fileName);
            fileInputStream = new FileInputStream(sentFile);
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(serverConnection.getOutputStream());
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(bufferedOutputStream);
            int readCharactere;
            while((readCharactere = fileInputStream.read()) != -1){
                outputStreamWriter.write(readCharactere);
            }
            
            /* Receive Confirmation */
            BufferedInputStream bufferedInputStream = new BufferedInputStream(serverConnection.getInputStream());
            InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
            while((readCharactere = inputStreamReader.read()) != (char)13){
                receivedMessageBuffer.append((char)readCharactere);
            }
            receivedMessage = receivedMessageBuffer.toString();
            
        } catch (FileNotFoundException ex) {
            Logger.getLogger(PeerToPeerServer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(PeerToPeerServer.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                fileInputStream.close();
            } catch (IOException ex) {
                Logger.getLogger(PeerToPeerServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    public void sendConfirmation(){
        BufferedOutputStream bufferedOutputStream = null;
        try {
            /* Send Confirmation. */
            String sentMessage = "ACK" + (char)13;
            bufferedOutputStream = new BufferedOutputStream(serverConnection.getOutputStream());
            OutputStreamWriter outputStreamWritter = new OutputStreamWriter(bufferedOutputStream);
            outputStreamWritter.write(sentMessage);
            outputStreamWritter.flush();
        } catch (IOException ex) {
            Logger.getLogger(PeerToPeerServer.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                bufferedOutputStream.close();
            } catch (IOException ex) {
                Logger.getLogger(PeerToPeerServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
        
    @Override
    public void run(){
        try {
            System.out.println("\nNew Thread created.");
            BufferedInputStream bufferedInputStream = null; 
            
            /* Receiving Message. */
                bufferedInputStream = new BufferedInputStream(serverConnection.getInputStream());
                InputStreamReader inputStreamReader = new InputStreamReader(bufferedInputStream);
                InputStream inputStream = serverConnection.getInputStream();
                int readCharactere;
                StringBuffer receivedMessage = new StringBuffer();
                while((readCharactere = inputStreamReader.read()) != (char)13){
                    receivedMessage.append((char) readCharactere);
                } 
                
                /* Check Message for Instructions. */ 
                String message = receivedMessage.toString();
                String messageParts[] = message.split(" ");
                System.out.println("\nMessage: " + message);
                String sentMessage = "";
                
                switch(messageParts[0]){
                    /* Receive a File Solicitaion. */
                    case "getFile":
                        sendConfirmation();
                        SendFile(messageParts[1]);
                        break;
                    /* Receive a File Update Notification. */    
                    case "upFile":
                        sendConfirmation();
                        receiveFile(messageParts[1]);
                        break;
                }
                /* Close Connecion. */
                serverConnection.close();
                System.out.println("\nThread closed.");
        } catch (IOException ex) {
            Logger.getLogger(PeerToPeerServer.class.getName()).log(Level.SEVERE, null, ex);
        }
}
    
    public static void main(String[] args){
        int serverPort = 8000;
        int counter = 0;
        fileList = new ArrayList();
        try {
            ServerSocket serverSocket = new ServerSocket(serverPort);
            System.out.println("Client Server Initialized");
            while (true){
                System.out.println("\nLoop:");
                Socket serverConnection = serverSocket.accept();
                Thread thread = new Thread(new PeerToPeerServer(serverConnection, ++counter));
                thread.start();
            }
        } 
        catch (IOException ex) {
            Logger.getLogger(PeerToPeerServer.class.getName()).log(Level.SEVERE, null, ex);
        } 
    }
    
    public class MyFile {
        private String fileName;
        private List<String> whoHasMe;
        private boolean beingWriten;
        
        public MyFile(String fileName, String iHaveYou){
            this.fileName = fileName;
            this.whoHasMe = new ArrayList();
            this.whoHasMe.add(iHaveYou);
            this.beingWriten = false;
        }
        
        public String getFileName(){
            return this.fileName;
        }
        
        public List<String> getWhoHasMe(){
            return this.whoHasMe;
        }
    }
}
    
